/**
 * Fichier FabriqueDao.java : Définition de classe
 * fr.unice.gnpt.core.dao.factory.FabriqueDao : Fabrique abstraite de fabrique
 * de DAO
 * 
 * Auteurs : Groupe GNPT : Gastinel, Nicolas, Pellegrino, Trovato
 */
package fr.unice.gnpt.core.dao.factory;

import fr.unice.gnpt.core.dao.DaoCours;
import fr.unice.gnpt.core.dao.DaoEnseignant;
import fr.unice.gnpt.core.dao.DaoException;
import fr.unice.gnpt.core.dao.DaoService;

/**
 * Classe abstraite gérant le type de fabrique de DAO à créer.
 * <p>
 * Il est important de toujours commencer par indiquer le type de fabrique de
 * DAO souhaité à l'aide de la méthode
 * {@link #setTypeFabriqueDao(TypeFabriqueDao)} avant de faire appel à la
 * méthode {@link #getFabriqueDao()}, auquel cas une exception de type
 * DaoException sera lancée. Après avoir indiqué le type de DAO souhaité, on
 * peut alors indiquer le nom du fichier de configuration de la connexion qu'on
 * souhaite faire transiter jusqu'aux DAO afin qu'ils ouvrent chacun séparemment
 * une connexion afin de pouvoir gérer les transactions. Pour ce faire utilisez
 * la méthode {@link #setNomFichierConfiguration(String)}.
 * <p>
 * Une fois ceci effectué lors de l'appel à la méthode {@link #getFabriqueDao()}
 * il sera retourné une fabrique respectant les critères précédemment définis.
 * <p>
 * <p>
 * Si la fabrique est de type JPA alors le fichier de configuration doit
 * contenir au moins les propriétés suivante :
 * <ul>
 * <li>jpa.user = ***</li>
 * <li>jpa.pass = ***</li>
 * <li>jpa.server = ***</li>
 * <li>jpa.server.type = ***</li>
 * <li>jpa.port = ***</li>
 * <li>jpa.database = ***</li>
 * </ul>
 * afin que les DAO créés depuis la fabrique puissent se connecter à la base de
 * données associée au système de persistance JPA.
 * 
 * @author gnpt
 * @version 0.1.3
 */
public abstract class FabriqueDao {
	/**
	 * La fabrique concrète en cours (singleton).
	 */
	private static FabriqueDao fabriqueCourante;
	/**
	 * Les types de persistance.
	 */
	private static TypeFabriqueDao typeFabriqueDao;
	/**
	 * Le nom du fichier de configuration si on veut passer une connexion à la
	 * fabrique qui s'occupera de transmettre le nom du fichier aux fabriques
	 * concrètes.
	 */
	private static String nomFichierConfiguration;

	/**
	 * Un des différents type de DAO que la fabrique créée par l'intermédiaire
	 * de cette fabrique abstraite doit savoir créer : ici un DAO pour la classe
	 * Cours.
	 * 
	 * @return un DAO pour la classe Cours.
	 */
	public abstract DaoCours getDaoCours();

	/**
	 * Un des différents type de DAO que la fabrique créée par l'intermédiaire
	 * de cette fabrique abstraite doit savoir créer : ici un DAO pour la classe
	 * Enseignant.
	 * 
	 * @return un DAO de type Enseignant.
	 */
	public abstract DaoEnseignant getDaoEnseignant();

	/**
	 * Un des différents type de DAO que la fabrique créée par l'intermédiaire
	 * de cette fabrique abstraite doit savoir créer : ici un DAO pour la classe
	 * Service.
	 * 
	 * @return un DAO de type Service.
	 */
	public abstract DaoService getDaoService();

	/**
	 * Renvoie une fabrique abstraite de DAO respectant le type de fabrique de
	 * DAO choisi auparavant via {@link #setTypeFabriqueDao(TypeFabriqueDao)}.
	 * 
	 * @see FabriqueDao#setTypeFabriqueDao(TypeFabriqueDao)
	 * 
	 * @return une fabrique abstraite de DAO respectant le type de fabrique de
	 *         DAO choisi auparavant via
	 *         {@link #setTypeFabriqueDao(TypeFabriqueDao)}.
	 * @throws DaoException
	 *             dans le cas ou la fabrique courante n'a pas été définie.
	 */
	public static FabriqueDao getFabriqueDao() throws DaoException {
		if (FabriqueDao.fabriqueCourante == null) {
			switch (FabriqueDao.typeFabriqueDao) {
			case DB4O:
				FabriqueDao.fabriqueCourante = new FabriqueDaoDb4o();
				break;
			case JPA:
				FabriqueDao.fabriqueCourante = new FabriqueDaoJpa();
				break;
			default:
				throw new DaoException(
						"La fabrique courante n'a pas été définie.");
			}
		}
		return FabriqueDao.fabriqueCourante;
	}

	/**
	 * Accesseur pour connaître le nom du fichier de configuration contenant les
	 * informations nécessaires à la création de la connexion associé au système
	 * de persistance devant être défini auparavant.
	 * 
	 * @return le nom du fichier de configuration contenant les informations
	 *         nécessaires à la création de la connexion.
	 */
	public static String getNomFichierConfiguration() {
		return nomFichierConfiguration;
	}

	/**
	 * Accesseur pour connaître le type de fabrique de DAO que cette fabrique
	 * produit.
	 * 
	 * @return le type de fabrique de DAO que cette fabrique produit.
	 */
	public static TypeFabriqueDao getTypeFabriqueDao() {
		return typeFabriqueDao;
	}

	/**
	 * Mutateur pour le nom du fichier de configuration contenant les
	 * informations nécessaires à la création de la connexion.
	 * <p>
	 * Réinitialise la fabrique de DAO.
	 * 
	 * @param nomFichierConfiguration
	 *            le nouveau nom du fichier de configuration contenant les
	 *            informations nécessaires à la création de la connexion.
	 */
	public static void setNomFichierConfiguration(String nomFichierConfiguration) {
		FabriqueDao.fabriqueCourante = null;
		FabriqueDao.nomFichierConfiguration = nomFichierConfiguration;
	}

	/**
	 * Mutateur pour le type de fabrique de DAO que cette fabrique produit.
	 * 
	 * @param type
	 *            le nouveau type de fabrique de DAO que cette fabrique doit
	 *            produire.
	 */
	public static void setTypeFabriqueDao(TypeFabriqueDao type) {
		/*
		 * On réinitialise la fabrique courante si le type est différent du type
		 * courant.
		 */
		if (type != FabriqueDao.typeFabriqueDao) {
			FabriqueDao.fabriqueCourante = null;
		}
		FabriqueDao.typeFabriqueDao = type;
	}
}
